package tests;

import common.IP;
import common.Utils;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Map;

public class Match extends Utils {
    public static String url="http://"+ IP.ip+"/game_hall.html";
    private JavascriptExecutor js;
    private boolean isFirstPlayer = false;

    public Match(){
        super(url);
        js = (JavascriptExecutor) driver;
    }

    //封装弹窗操作
    public void WaitAlert(WebDriver driver){
        //显式等待弹窗的出现
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
        Alert alert = null;
        try {
            //检测弹窗的存在，存在会显式返回一个有效的alert对象
            alert = wait.until(ExpectedConditions.alertIsPresent());
            alert.accept();
        }catch (Exception e){
            System.out.println("MatchFail");
        }
    }

    /*
        删除cookie强制登录
     */
    public void withoutLogin() throws InterruptedException {
        //删除所有cookie
        driver.manage().deleteAllCookies();
        //刷新
        driver.navigate().refresh();
        WaitAlert(driver);
        Thread.sleep(2000);
    }

    /*
        匹配并开始游戏,并判断哪方是先手
     */
    public void SingleMatch() throws InterruptedException {
        //谷歌浏览器的弹窗会阻碍自动化进行，所以进行强制等待
        Thread.sleep(6000);
        //获取标签信息
        WebElement element = driver.findElement(By.cssSelector("#match-button"));
        String text = element.getText();
        assert text.equals("开始匹配");
        //点击匹配
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        driver.findElement(By.cssSelector("#match-button")).click();
//        wait.until(ExpectedConditions.textToBe(By.cssSelector("#match-button"),"匹配中...(点击停止)"));

        // 等待进入游戏房间（等待#screen元素出现）
        wait = new WebDriverWait(driver, Duration.ofSeconds(30));  // 增加等待时间，因为匹配可能需要一段时间
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#screen")));

        // 等待一下，确保页面完全加载
        Thread.sleep(2000);

        // 判断是否为先手 - 修改判断逻辑
        try {
            // 检查是否有"轮到你落子"的提示，同时确认棋盘上没有任何棋子
            String checkFirstScript =
                    "var screen = document.querySelector('#screen');" +
                            "var pieces = document.querySelectorAll('#chess div.piece');" +
                            "return {" +
                            "    message: screen ? screen.textContent : ''," +
                            "    pieceCount: pieces.length" +
                            "};";

            Map<String, Object> result = (Map<String, Object>) js.executeScript(checkFirstScript);
            String screenMessage = (String) result.get("message");
            Long pieceCount = (Long) result.get("pieceCount");

            // 只有当提示出现且棋盘上没有棋子时才是先手
            isFirstPlayer = screenMessage.contains("轮到你落子") && pieceCount == 0;
            System.out.println("屏幕提示: " + screenMessage);
            System.out.println("棋盘上的棋子数: " + pieceCount);
            System.out.println("是否为先手: " + isFirstPlayer);
        } catch (Exception e) {
            System.out.println("无法判断先后手: " + e.getMessage());
            isFirstPlayer = false;  // 默认为后手
        }
    }

    private void playChess(int row, int col) {
        try {
            // 等待棋盘元素加载
            WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
            wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#chess")));

            // 注入JavaScript函数来模拟点击
            String script = String.format(
                    "const chess = document.querySelector('#chess');" +
                            "const rect = chess.getBoundingClientRect();" +
                            "const x = rect.left + (%d * 30) + 15;" +
                            "const y = rect.top + (%d * 30) + 15;" +
                            "const clickEvent = new MouseEvent('click', {" +
                            "    bubbles: true," +
                            "    cancelable: true," +
                            "    view: window," +
                            "    clientX: x," +
                            "    clientY: y," +
                            "    offsetX: (%d * 30) + 15," +
                            "    offsetY: (%d * 30) + 15" +
                            "});" +
                            "chess.dispatchEvent(clickEvent);",
                    col, row, col, row
            );

            js.executeScript(script);
            // 等待一下，确保落子动作完成
            Thread.sleep(1000);
        } catch (Exception e) {
            System.out.println("落子失败: " + e.getMessage());
        }
    }

    private boolean isFirstMove(ArrayList<ArrayList<Long>> board) {
        int pieceCount = 0;
        for (ArrayList<Long> row : board) {
            for (Long cell : row) {
                if (cell != 0) pieceCount++;
            }
        }
        return pieceCount <= 1;  // 只有一个或没有棋子时是第一步
    }

    private boolean isMyTurn() {
        try {
            // 获取提示信息
            String screenText = driver.findElement(By.cssSelector("#screen")).getText();
            System.out.println("当前提示: " + screenText);

            // 首先检查是否是游戏结束的消息
            if (screenText.contains("你输了！") ||
                    screenText.contains("你赢了!") ||
                    screenText.contains("对方掉线，你获胜!")) {
                return false;  // 游戏结束时返回false，让主循环去处理结束逻辑
            }

            // 根据提示判断是否轮到我方下棋
            if (screenText.contains("轮到你落子")) {
                return true;
            } else if (screenText.contains("轮到对方落子")) {
                return false;
            } else {
                // 如果提示不明确，保持当前状态
                System.out.println("无法判断当前轮次，等待下一次检查");
                return false;
            }
        } catch (Exception e) {
            System.out.println("检查轮次出错: " + e.getMessage());
            return false;
        }
    }

    public void startAutoPlay() throws InterruptedException {
        System.out.println("开始自动对弈");

        while (true) {
            try {
                Thread.sleep(1000);  // 每秒检查一次

                // 获取当前屏幕文本
                String screenText = driver.findElement(By.cssSelector("#screen")).getText();

                // 首先检查是否是游戏结束的情况
                if (screenText.contains("你输了！") ||
                        screenText.contains("你赢了!") ||
                        screenText.contains("对方掉线，你获胜!")) {

                    System.out.println("游戏结束，原因: " + screenText);

                    // 等待返回大厅按钮出现并可点击
                    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
                    try {
                        WebElement returnButton = wait.until(ExpectedConditions.elementToBeClickable(
                                By.cssSelector("body > div.container > div > button")));
                        returnButton.click();

                        // 等待页面跳转并验证标题
                        wait.until(ExpectedConditions.titleIs("游戏大厅"));
                        String title = driver.getTitle();
                        assert title.equals("游戏大厅");
                        System.out.println("成功返回游戏大厅");
                        break;
                    } catch (Exception e) {
                        System.out.println("等待返回按钮出现或点击失败: " + e.getMessage());
                    }
                    continue;  // 继续检查，直到可以返回大厅
                }

                // 如果游戏未结束，继续正常的游戏流程
                if (isMyTurn()) {
                    System.out.println("轮到我方下棋");
                    autoPlay();
                    Thread.sleep(500);  // 下棋后稍等片刻
                } else {
                    System.out.println("等待对方下棋");
                }

                // 检查其他结束条件
                String gameEndScript =
                        "return document.querySelector('.win-info') !== null || " +
                                "document.querySelector('.lose-info') !== null || " +
                                "document.querySelector('.tie-info') !== null;";

                Boolean hasEndInfo = (Boolean) js.executeScript(gameEndScript);
                if (hasEndInfo) {
                    System.out.println("检测到游戏结束信息");
                    // 等待返回大厅按钮出现并可点击
                    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
                    try {
                        WebElement returnButton = wait.until(ExpectedConditions.elementToBeClickable(
                                By.cssSelector("body > div.container > div > button")));
                        returnButton.click();

                        // 等待页面跳转并验证标题
                        wait.until(ExpectedConditions.titleIs("游戏大厅"));
                        String title = driver.getTitle();
                        assert title.equals("游戏大厅");
                        System.out.println("成功返回游戏大厅");
                        break;
                    } catch (Exception e) {
                        System.out.println("等待返回按钮出现或点击失败: " + e.getMessage());
                    }
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            } catch (Exception e) {
                System.out.println("自动下棋过程出错: " + e.getMessage());
                Thread.sleep(1000);  // 出错后等待一秒再继续
            }
        }
    }

    private void autoPlay() {
        try {
            // 随机选择一个位置下棋
            int row = (int) (Math.random() * 15);
            int col = (int) (Math.random() * 15);

            // 验证位置是否已被占用
            String verifyScript = String.format(
                    "var piece = document.querySelector('#chess div.piece[data-row=\"%d\"][data-col=\"%d\"]');\n" +
                            "return !piece;",  // 返回true表示位置为空
                    row, col
            );

            Boolean isEmpty = (Boolean) js.executeScript(verifyScript);
            if (isEmpty) {
                System.out.println("准备在位置 [" + row + "][" + col + "] 下棋");
                playChess(row, col);
            } else {
                System.out.println("位置 [" + row + "][" + col + "] 已被占用，重新尝试");
                autoPlay();  // 递归尝试新的位置
            }
        } catch (Exception e) {
            System.out.println("下棋出错: " + e.getMessage());
        }
    }

}
